package is.xdumper;

import is.bean.entity.department.DepartmentBeanRemote;
import is.bean.entity.department.Department;
import is.bean.entity.department.DepartmentBeanRemoteHome;
import is.bean.entity.employee.Employee;
import is.bean.entity.employee.EmployeeBeanRemoteHome;
import is.bean.entity.region.Region;
import is.bean.entity.region.RegionBeanRemoteHome;
import is.xdumper.type.Dump;
import java.rmi.RemoteException;
import java.util.*;
import javax.ejb.CreateException;
import javax.ejb.FinderException;

/**
 * Writes dump to DB
 *
 * @author aspr0
 */
public class XdumperImporter
{
    private Dump dump;
    private DepartmentBeanRemoteHome departmentHome;
    private EmployeeBeanRemoteHome employeeHome;
    private RegionBeanRemoteHome regionHome;
    private HashMap<Integer, Integer> bossMap = new HashMap<Integer, Integer>();
    /**
     * Deferred Boss department
     */
    private Department dbd;

    public Dump getDump()
    {
        return dump;
    }

    public void setDump(Dump dump)
    {
        this.dump = dump;
    }

    public void setDepartmentHome(DepartmentBeanRemoteHome departmentHome)
    {
        this.departmentHome = departmentHome;
    }

    public void setEmployeeHome(EmployeeBeanRemoteHome employeeHome)
    {
        this.employeeHome = employeeHome;
    }

    public void setRegionHome(RegionBeanRemoteHome regionHome)
    {
        this.regionHome = regionHome;
    }

    public void doImport() throws FinderException, RemoteException, CreateException
    {
        Set<Department> departmentTable = dump.getDepartmentTable();
        Set<Employee> employeeTable = dump.getEmployeeTable();
        Set<Region> regionTable = dump.getRegionTable();

//        while (regionTable.size() > 0)
//        {
//            int id = -1;
//            Iterator<Region> regions = regionTable.iterator();
//
//            while (regions.hasNext())
//            {
//                Region region = regions.next();
//
//                if (dump.getDumpReferences())
//                /* Making hierarchial insert */
//                {
//                    if (inserted)
//                    {
//                        int pId = region.getParentId();
//
//                        if (pId == id)
//                        /* If a child of previous inserted */
//                        {
//                            id = region.getId();
//
//                            if (regionHome.entityExist(id))
//                            {
//                                regionHome.findByPrimaryKey(id).setData(region);
//                            }
//                            else
//                            {
//                                regionHome.createInstance(region);
//                            }
//                            regions.remove();
//                            inserted = true;
//                        }
//                        else
//                        {
//                            inserted = false;
//                        }
//                    }
//                    else
//                    /* Starting with top of hierarchy */
//                    {
//                        id = region.getId();
//                        int pId = region.getParentId();
//
//                        if (pId == 0)
//                        {
//                            if (regionHome.entityExist(id))
//                            {
//                                regionHome.findByPrimaryKey(id).setData(region);
//                            }
//                            else
//                            {
//                                regionHome.createInstance(region);
//                            }
//                            regions.remove();
//                            inserted = true;
//                        }
//                        else
//                        {
//                            inserted = false;
//                        }
//                    }
//                }
//                else
//                /* No-order insert - any dependence already in db */
//                /* Except you re importing one top-level region which need no deps */
//                {
//                    id = region.getId();
//
//                    if (regionHome.entityExist(id))
//                    {
//                        regionHome.findByPrimaryKey(id).setData(region);
//                    }
//                    else
//                    {
//                        regionHome.createInstance(region);
//                    }
//                    regions.remove();
//                }
//            }
//        }
        boolean found = false;
        LinkedList<Integer> stack = new LinkedList<Integer>();
        /* Starting at the hier top */
        stack.add(0);

        while (regionTable.size() > 0)
        {
            int id = 0;
            int searchPId = stack.getLast();
            Iterator<Region> regions = regionTable.iterator();

            while (regions.hasNext())
            {
                Region region = regions.next();

                if (region.getParentId().equals(searchPId))
                {
                    id = region.getId();

                    if (regionHome.entityExist(id))
                    {
                        regionHome.findByPrimaryKey(id).setData(region);
                    }
                    else
                    {
                        regionHome.createInstance(region);
                    }
                    
                    regions.remove();
                    found = true;
                    break;
                }
                else
                {
                    found = false;
                }
            }

            if (found)
            {
                stack.add(id);
            }
            else
            {
                stack.removeLast();
            }
        }

        found = false;
        stack.add(0);
        while (departmentTable.size() > 0)
        {
            int id = 0;
            int searchPId = stack.getLast();
            Iterator<Department> departments = departmentTable.iterator();

            while (departments.hasNext())
            {
                Department department = departments.next();

                if (department.getParentId().equals(searchPId))
                {
                    id = department.getId();
                    deferBoss(department);

                    if (departmentHome.entityExist(id))
                    {
                        departmentHome.findByPrimaryKey(id).setData(dbd);
                    }
                    else
                    {
                        departmentHome.createInstance(dbd);
                    }

                    departments.remove();
                    found = true;
                    break;
                }
                else
                {
                    found = false;
                }
            }

            if (found)
            {
                stack.add(id);
            }
            else
            {
                stack.removeLast();
            }
        }

        Iterator<Employee> employees = employeeTable.iterator();
        while (employees.hasNext())
        {
            Employee employee = employees.next();

            int id = employee.getId();

            if (employeeHome.entityExist(id))
            {
                employeeHome.findByPrimaryKey(id).setData(employee);
            }
            else
            {
                employeeHome.createInstance(employee);
            }
        }

        /* Restoring bosses */
        Iterator<Integer> bossIds = bossMap.keySet().iterator();
        while (bossIds.hasNext())
        {
            Integer id = bossIds.next();

            DepartmentBeanRemote departmentRemote = departmentHome.findByPrimaryKey(id);
            Department department = departmentRemote.getData();
            department.setBossId(bossMap.get(id));
            departmentRemote.setData(department);
        }
    }

    private void deferBoss(Department department)
    {
        bossMap.put(department.getId(), department.getBossId());
        dbd = (Department) department.clone();
        dbd.setBossId(0);
    }
}
